package com.veer.shop.service.impl.admin;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.veer.shop.config.Constants;
import com.veer.shop.config.OpResult;
import com.veer.shop.config.ResponseCodeEnum;
import com.veer.shop.factory.CustomerLoginFactory;
import com.veer.shop.mapper.AdminUserMapper;
import com.veer.shop.pojo.User;
import com.veer.shop.pojo.CustomerLogin;
import com.veer.shop.pojo.ResponseData;
import com.veer.shop.pojo.Token;
import com.veer.shop.service.admin.AuthorizeService;
import com.veer.shop.service.admin.CustomerLoginService;
import com.veer.shop.utils.EcryptUtil;
import com.veer.shop.utils.JwtUtil;
import com.veer.shop.utils.RedisUtil;
import com.veer.shop.utils.ResponseUtil;
/**
 * JWT token获取业务类
 * 
 * @author WangBin
 * 2021年1月4日-上午10:32:12
 */
@Service
public class AuthorizeServiceImpl implements AuthorizeService {
	
	private static final Logger logger = LoggerFactory.getLogger(AuthorizeServiceImpl.class);
	
	@Autowired
	private AdminUserMapper adminUserMapper;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private ObjectMapper jackJsonMapper;
	@Autowired
	private CustomerLoginFactory customerLoginFactory;
	
	/**
	 * 获取客户Token
	 */
	@Override
	public ResponseData<?> getCustomerToken(CustomerLogin customerLogin) {
		
		logger.info("[获取会员Token] " + customerLogin.toString());

		if(StringUtils.isEmpty(customerLogin.getLoginMethod()) || !Constants.CUSTOMER_LOGIN_METHOD_LIST.contains(customerLogin.getLoginMethod())) {
			// 参数错误
			return ResponseUtil.error("未知的登录方式");
		}
		// 获取登录业务处理类
		CustomerLoginService customerLoginService = customerLoginFactory.getCustomerLoginService(customerLogin.getLoginMethod());
		OpResult<Token> opResult = customerLoginService.login(customerLogin.getUsername(), customerLogin.getPassword());
		if(opResult.getFlag()) {
			return ResponseUtil.success(opResult.getData());
		}
		return ResponseUtil.error(opResult.getMessage());
	}
	
	/**
	 * 获取后台用户Token
	 */
	@Override
	public ResponseData<?> getAdminToken(String username, String password) {
		
		logger.info("[获取管理员Token] 用户名：" + username + " 密码：" + password);
		
		if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
			// 参数错误
			return ResponseUtil.error(ResponseCodeEnum.GET_AUTH_TOKEN_PARAMS_ERROR);
		}
		
		// 根据用户名查找管理员信息
		User adminUserEntity = adminUserMapper.selectAdminUserByUserName(username);
		
		if(ObjectUtils.isEmpty(adminUserEntity)) {
			// 用户账户或密码错误
			return ResponseUtil.error(ResponseCodeEnum.GET_AUTH_TOKEN_ERROR);
		}

		// 校验管理员密码
		String md5Pwd = EcryptUtil.generateMd5(password, adminUserEntity.getSecret());
		if(!md5Pwd.equals(adminUserEntity.getPassword())) {
			// 用户账户或密码错误
			return ResponseUtil.error(ResponseCodeEnum.GET_AUTH_TOKEN_ERROR);
		}
		
		// 根据用户ID 获取 可用 token
		// 首先从缓存中获取用户的token，如果没有则重新生成token并存入缓存里
		// 存入缓存使用token作为key，value为用户信息：用户ID，用户名称
		Token token = new Token();
		// 缓存不存在或者token过期则重新生成token并将新token存入缓存中
		String adminTokenKey = Constants.REDIS_PREFIX_USER_TOKEN + adminUserEntity.getUserId();
		String adminExpiredKey = Constants.REDIS_PREFIX_USER_EXPIRED + adminUserEntity.getUserId();
		if(!redisUtil.hasKey(adminTokenKey) || redisUtil.getExpire(adminTokenKey, TimeUnit.MILLISECONDS) < 0) {
			token = JwtUtil.generate(adminUserEntity.getUserId(), Constants.JWT_PASSOWRD_SECRET);
			// 新token存入缓存 默认减去5秒的生存期
			redisUtil.setEx(adminTokenKey, token.getToken(), Constants.JWT_TOKEN_LIFE_TIME - 5 * 1000, TimeUnit.MILLISECONDS);
			redisUtil.setEx(adminExpiredKey, String.valueOf(token.getExpiredAt()), Constants.JWT_TOKEN_LIFE_TIME - 5, TimeUnit.MILLISECONDS);
			String userJsonStr = "";
			try {
				userJsonStr = jackJsonMapper.writeValueAsString(adminUserEntity);
			} catch (JsonProcessingException e) {
				e.printStackTrace();
			}
			// 用户信息
			redisUtil.setEx(token.getToken(), userJsonStr, Constants.JWT_TOKEN_LIFE_TIME - 5 * 1000, TimeUnit.MILLISECONDS);
		}

		// 从缓存中获取token
		token.setToken(redisUtil.get(adminTokenKey));
		token.setExpiredAt(Long.valueOf(redisUtil.get(adminExpiredKey)));
		return ResponseUtil.success(token);
	}
}